import java.util.Date;
import java.util.logging.Logger;
import src.de.checker.hochzeit.domain.util.*;
import src.de.checker.hochzeit.domain.user.*;
import src.de.checker.hochzeit.domain.checkliste.*;
import src.de.checker.hochzeit.konstanten.*
import src.de.checker.hochzeit.util.*;
import com.google.appengine.api.datastore.*
import static com.google.appengine.api.datastore.FetchOptions.Builder.*
/**
 * Verwaltet die Funktionen, die für die Checkliste nötig sind.
 */
Logger log = Logger.getLogger('ChecklisteController');

def myuser = session.getAttribute(Konstanten.SESSION_USER);

if(myuser != null)
{
	if(params?.index ==~ /(?i)true/)
	{
		index()
	}
	if(params?.save ==~ /(?i)true/)
	{
		save()
	}
	if(params?.createdefault ==~ /(?i)true/)
	{
		createFromDefault()
	}
	if(params?.delete ==~ /(?i)true/)
	{
		delete()
	}
	if(params?.update ==~ /(?i)true/)
	{
		update()
	}
	if(params?.edit ==~ /(?i)true/)
	{
		edit()
	}
	if(params?.show ==~ /(?i)true/)
	{
		show()
	}
	if(params?.create ==~ /(?i)true/)
	{
		create()
	}
	if(params?.saveitem ==~ /(?i)true/)
	{
		saveitem()
	}
}
private void index()
{
	def myuser = session.getAttribute(Konstanten.SESSION_USER);

	//Kategorien suchen
	def query1 = new Query(Konstanten.CKATEGORIE)
	query1.addSort("id", Query.SortDirection.ASCENDING)
	PreparedQuery preparedQuery1 = datastore.prepare(query1)
 	def kategorien = preparedQuery1.asList( withLimit(300) )
 	//Checklisteneinträge für die Feier des angemeldeten Benutzers suchen
 	def query = new Query(Konstanten.CHECKLISTE)
	query.addFilter("feier", Query.FilterOperator.EQUAL, myuser.feier)
	query.addSort("fertigBis", Query.SortDirection.ASCENDING)
	query.addSort("kurzbeschreibung", Query.SortDirection.ASCENDING)
	PreparedQuery preparedQuery = datastore.prepare(query)
 	def checkliste = preparedQuery.asList( withLimit(300) )
	HashMap liste = new HashMap();
	
	Long firstkat = -1
 	boolean firstkatIsSet = false
 	
 	for(kat in kategorien)
 	{
 		String b = kat.beschreibung
 		Long id = kat.id
 		List katcheck = new ArrayList()
 		for(check in checkliste)
 		{
 			if(kat.key == check.kategorie)
 			{
 				katcheck.add(check)
 				if(!firstkatIsSet)
 				{
 					firstkat = id
 					firstkatIsSet = true
 				}
 			}
 		}
 		liste.put id, katcheck
 	}
	//log.info('Map: '+liste)
 	
	request['list'] = checkliste
	request['firstkat'] = firstkat
 	request['kat'] = kategorien
 	//System.out.println(kategorien)
 	request['checkmap'] = liste
 	//log.info('Anzahl der Einträge in der Checkliste: '+checkliste.size())
 	forward '/checkliste/uebersicht.gtpl'
}
/**
 * Löscht die Checkliste für den angemeldeten Benutzer
 * @param feier
 */
private void deleteChecklistForFeier(String feier)
{
	def user = session.getAttribute(Konstanten.SESSION_USER)
	def query = new Query(Konstanten.CHECKLISTE)
	query.addFilter("feier", Query.FilterOperator.EQUAL, feier)
	PreparedQuery preparedQuery = datastore.prepare(query)
	def entities = preparedQuery.asList( withLimit(1000) )
	int counter = 0
	for(i in entities)
	{
		counter++
		i.delete()
	}
	if(counter > 0)
	{
		log.info('Benutzer: '+user+' die alten Einträge der Checkliste gelöscht (Anzahl:'+counter+')')
		String message =  'Alle Einträge aus der Checkliste für die Feier '+feier+' gelöscht.'
		createTracer(Konstanten.TRACER_DELETE ,message)
	}
}
/**
 * Erstellt eine Checkliste für die Feier des angemeldeten Benutzers
 * aus den Einträgen der Default-Checkliste
 */
private void createFromDefault()
{
	def user = session.getAttribute(Konstanten.SESSION_USER)
	String feier = user.feier
	//Eigentlich unnötig, weil diese Funktion laut Auth-Filter nur den Rollen 0 zugeordnet ist
	if(user.rolle == 0)
	{
		deleteChecklistForFeier(feier)
		
		def query = new Query(Konstanten.DEFAULT_CHECKLISTE)
		PreparedQuery preparedQuery = datastore.prepare(query)
	 	def entities = preparedQuery.asList( withLimit(300) )
	 	int counter = 0
	 	Key myuser = user.key
	 	for(i in entities)
	 	{
	 		counter++
	 		Checkliste item = new Checkliste();
	 		item.kurzbeschreibung = i.kurzbeschreibung
	 		item.anmerkung = i.anmerkung
	 		item.kategorie = i.kategorie
	 		item.prio = i.prio
	 		
	 		item.status = new Long(0)
	 		item.eingestelltAm = Datehelper.getNow()
	 		item.zulBearbeitetAm = null
	 		item.fertigBis = null
	 		item.verantwortlicher = myuser	
	 		item.feier = feier
	 		item.notified = false
	 		
	 		Entity e2 = item as Entity
	 		e2.save()
	 	}
		if(counter > 0)
		{
			log.info('Benutzer: '+user+' hat eine neue Checkliste aus dem Defaultset erstellt')
			log.info('Items (Anzahl:'+counter+') aus der Default Checkliste für Feier '+feier+' übernommen.')
			String message = 'Neue Checkliste aus Default Checkliste für Feier '+feier+'(Anzahl:'+counter+')'
			createTracer(Konstanten.TRACER_CREATE ,message)
		}
	}
	else
	{
		String message = 'Versuch eine neue Checkliste aus der Defaultcheckliste zu erstellen. '
		createTracer(Konstanten.TRACER_VERBOTEN ,message)
		log.warning("Der Benutzer "+user+"hat versucht eine Default Checkliste zu erstellen, obwohl er " +
				"nicht zum Brautpaar gehört! Abgebrochen!")
	}	
	index()
}
private void save()
{
	Entity entity = new Entity(Konstanten.CHECKLISTE)
	entity['kurzbeschreibung'] = params.kurzbeschreibung
	entity['anmerkung'] = params.anmerkung
	entity['feier'] = session.getAttribute(Konstanten.SESSION_USER).feier
	
	entity['prio'] = getKey(params.prio,Konstanten.PRIO)
	entity['kategorie'] = getKey(params.kategorie,Konstanten.CKATEGORIE)
	entity['status'] = new Long(0)
	
	entity['eingestelltAm'] = Datehelper.getNow()
	entity['zulBearbeitetAm'] = null
	entity['fertigBis'] = null
	
	entity['verantwortlicher'] = session.getAttribute(Konstanten.SESSION_USER).key	
	entity['notified'] = false
	
	entity.save()
	
	log.info("Checklisteneintrag gespeichert: "+entity)
	
	index()
}
/**
 * Löscht einen Checklisteneintrag
 */
private void delete()
{
	def myuser = session.getAttribute(Konstanten.SESSION_USER);

	
	try
	{
		Key k = KeyFactory.stringToKey(params.key)
		def checkitem = datastore.get(k);
		//Gehört der zu löschende Eintrag auch zum Benutzer?
		if(checkitem.feier.equals(myuser.feier) )
		{
			log.info ('Lösche Checklisteneintrag: '+checkitem+' [Gelöscht von: '+myuser+"]")
			createTracer(Konstanten.TRACER_DELETE, 'Checklisteneintrag '+checkitem.key+' '+checkitem.kurzbeschreibung+' gelöscht')
			checkitem.delete()
		}
		else
		{
			String message = 'VERBOTEN: Der Benutzer hat versucht ein Checklisteneintrag zu löschen, dass nicht zur eigenen Feier gehört '+checkitem.key
			createTracer(Konstanten.TRACER_VERBOTEN, message)
		    log.warning("checkliste.delete(): Checklistitem gehört nicht zur eigenen Feier:"+checkitem+" Benutzer der gesucht hat: "+myuser)
		}
	}
	catch(Exception e)
	{
		String message = 'VERBOTEN: Es wurde ein Checkitem zu löschen, das es nicht gibt. params.key: '+params.key 
		createTracer(Konstanten.TRACER_VERBOTEN, message)
		log.warning(e.toString())
		log.warning("checkliste.delete(): Checklistitem nicht gefunden zum löschen. Benutzer der gesucht hat: "+myuser+" Params: "+params)
	}
	redirect '/checkliste?active='+params.active
}

private Key getKey(String id, String kind)
{
	long mid = new Long(id).longValue()
	Key k = KeyFactory.createKey(kind,mid)
	return k
}
private void update()
{
	def nutzer = session.getAttribute(Konstanten.SESSION_USER)
	try
	{
		Key k = KeyFactory.stringToKey(params.key)
		def checkitem = datastore.get(k);
		//Überprüfen, ob der Eintrag zur eigenen Feier gehört
		if(checkitem.feier.equals(nutzer.feier) )
		{
			//Ist der Benutzer auch der Verantwortliche
			if(checkitem.verantwortlicher == nutzer.key)
			{
				checkitem.zulBearbeitetAm = Datehelper.getNow()
				createitem(checkitem)
				String message = 'Checklisteneintrag aktualisiert: '+checkitem.key
				createTracer(Konstanten.TRACER_UPDATE, message)
				request.message = 'Checklisteneintrag '+checkitem.kurzbeschreibung+' überarbeitet.'
			}
			else
			{
				String message = 'Der Benutzer hat versucht ein Checklisteneintrag zu updaten, für das er nicht verantwortlich ist '+checkitem.key
				createTracer(Konstanten.TRACER_VERBOTEN, message)
				log.warning('Benutzer '+nutzer.anzeigename+' ['+nutzer.key+'] hat versucht ein Cecklistenitem' +
						' zu updaten, das nicht zu ihm gehört: '+checkitem.key+' gehört zu: '+checkitem.verantwortlicher)
				
			}
			
		}
		else
		{
			String message = 'Der Benutzer hat versucht ein Checklisteneintrag zu updaten, dass nicht zur eigenen Feier gehört '+checkitem.key
			createTracer(Konstanten.TRACER_VERBOTEN, message)
		}
		
	}
	catch(Exception e)
	{
		String message = 'Es wurde ein Checkitem zu updaten, das es nicht gibt. params.key: '+params.key 
		createTracer(Konstanten.TRACER_VERBOTEN, message)
		log.warning(e.toString())
		log.warning("checkliste.update(): Checklistitem nicht gefunden zum update. Benutzer der gesucht hat: "+nutzer)
	}
	index()
}
private void createitem(Entity checkitem)
{
	checkitem.kurzbeschreibung = params.kurzbeschreibung
	checkitem.anmerkung = params.anmerkung
	try
	{
		Long status = new Long(params.status)
		checkitem.status = status
	}
	catch(Exception e)
	{
		log.warning(e.toString())
	}
	String katid = params.kategorie
	Key kat = getKey(katid, Konstanten.CKATEGORIE)
	checkitem.kategorie = kat
	
	String prioid = params.prio
	Key pr = getKey(prioid, Konstanten.PRIO)
	checkitem.prio = pr
	
	String verid = params.verantwortlicher
	Key ver = getKey(verid, Konstanten.GAST)
	checkitem.verantwortlicher = ver
	
	String dl = params.fertigBis
	checkitem.fertigBis = Datehelper.string2Date(dl,"dd.MM.yyyy")
	
	checkitem.notified = false
	
	checkitem.save()
}
private void create()
{
	createandedit()
	forward '/checkliste/create.gtpl'
}
private void show()
{
	def myuser = session.getAttribute(Konstanten.SESSION_USER);

	try
	{
		Key k = KeyFactory.stringToKey(params.key)
		def entity = datastore.get(k);
		if(entity.feier.equals(myuser.feier))
		{
			request['checkitem'] =  entity
			createandedit()
			forward '/checkliste/show.gtpl'
		}
		else
		{
			String message = 'Der Benutzer will ein Checkitem anschauen, dass nicht zur eigenen Feier gehört. '+entity.key
			createTracer(Konstanten.TRACER_VERBOTEN, message)
			log.warning("checkliste.show(): Item gehört nicht zur eigenen feier:"+entity+" Benutzer der gesucht hat: "+session.getAttribute(Konstanten.SESSION_USER))
			index()
		}
	}
	catch(Exception e)
	{
		String message = 'Es wurde ein Checkitem anzuzeigen, das es nicht gibt. params.key: '+params.key 
		createTracer(Konstanten.TRACER_VERBOTEN, message)
		log.warning(e.toString())
		log.warning("checkliste.show(): Item nicht gefunden zum anzeigen. Benutzer der gesucht hat: "+session.getAttribute(Konstanten.SESSION_USER))
		index()
	}
}
private void edit()
{
	def myuser = session.getAttribute(Konstanten.SESSION_USER);

	try
	{
		Key k = KeyFactory.stringToKey(params.key)
		def entity = datastore.get(k);
		if(entity.feier.equals(myuser.feier))
		{
			if(entity.verantwortlicher == myuser.key)
			{
				request['checkitem'] =  entity
				createandedit()
				forward '/checkliste/edit.gtpl'
			}
			else
			{
				String message = 'Der Benutzer will ein Checkitem editieren, für das er nicht verantwortlich ist: '+entity.key
				createTracer(Konstanten.TRACER_VERBOTEN, message)
				log.warning('Benutzer '+myuser.anzeigename+' ['+myuser.key+'] hat versucht ein Cecklistenitem' +
						' zu editieren, das nicht zu ihm gehört: '+entity.key+' gehört zu: '+entity.verantwortlicher)
				index()
			}
		}
		else
		{
			String message = 'Der Benutzer will ein Checkitem editieren, dass nicht zur eigenen Feier gehört: '+entity.key
			createTracer(Konstanten.TRACER_VERBOTEN, message)
			log.warning("checkliste.edit(): Item gehört nicht zur eigenen feier:"+entity+" Benutzer der gesucht hat: "+session.getAttribute(Konstanten.SESSION_USER))
			index()
		}
	}
	catch(Exception e)
	{
		String message = 'Es wurde ein Checkitem zu editieren, das es nicht gibt. params.key: '+params.key 
		createTracer(Konstanten.TRACER_VERBOTEN, message)
		log.warning(e.toString())
		log.warning("checkliste.edit(): Item nicht gefunden zum editieren. Benutzer der gesucht hat: "+session.getAttribute(Konstanten.SESSION_USER))
		index()
	}
}
private void saveitem()
{
	def checkitem = new Entity(Konstanten.CHECKLISTE)
	checkitem.eingestelltAm = Datehelper.getNow()
	checkitem.feier = session.getAttribute(Konstanten.SESSION_USER).feier
	createitem(checkitem)
	log.info("Checklisteneintrag erstellt:"+checkitem.key)
	
	index()
}
private void createandedit()
{
	def kquery = new Query(Konstanten.CKATEGORIE)
	kquery.addSort("id", Query.SortDirection.ASCENDING)
	PreparedQuery kpreparedQuery = datastore.prepare(kquery)
	def entitiesk = kpreparedQuery.asList( withLimit(100) )
	request['listkat'] = entitiesk
	
	def pquery = new Query(Konstanten.PRIO)
	pquery.addSort("id", Query.SortDirection.ASCENDING)
	PreparedQuery ppreparedQuery = datastore.prepare(pquery)
	def entitiesp = ppreparedQuery.asList( withLimit(100) )
	request['listprio'] = entitiesp
	
	def uquery = new Query(Konstanten.GAST)
	uquery.addFilter("feier", Query.FilterOperator.EQUAL, session.getAttribute(Konstanten.SESSION_USER).feier)
	Collection col = new ArrayList();
	col.add(new Long(0))
	col.add(new Long(1))
	uquery.addFilter("rolle", Query.FilterOperator.IN, col)
	uquery.addSort("rolle", Query.SortDirection.ASCENDING)
	PreparedQuery upreparedQuery = datastore.prepare(uquery)
	def entitiesu = upreparedQuery.asList( withLimit(100) )
	request['listuser'] = entitiesu
	
}

private void createTracer(String message)
{
	createTracer(Konstanten.TRACER_FORGOT, message);
}
private void createTracer(String type, String message) {
	try
	{
		def myuser = session.getAttribute(Konstanten.SESSION_USER);

		Tracer t = new Tracer()
	    t.ipadresse = request.getRemoteAddr()
	    t.user = myuser.key
	    t.type = type
	    t.nachricht = message
	    t.datum = Datehelper.getNow()
	    Entity e2 = t as Entity
		e2.save()
	}
	catch(Exception e)
	{
		
	}
}